//package consulTest.GateWayLog;//package com.example.consulTest.GateWayLog;
//
//import com.meihaofenqi.loan.knot.constant.GateWayConstant;
//import com.meihaofenqi.loan.knot.entity.dtos.LogDTO;
//import com.meihaofenqi.loan.knot.utils.GenerateIdUtils;
//import com.meihaofenqi.loan.knot.utils.LogHelper;
//import io.netty.buffer.UnpooledByteBufAllocator;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang.StringUtils;
//import org.reactivestreams.Publisher;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.core.io.buffer.DataBufferFactory;
//import org.springframework.core.io.buffer.NettyDataBufferFactory;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
//import org.springframework.http.server.reactive.ServerHttpResponse;
//import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StopWatch;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Flux;
//import reactor.core.publisher.Mono;
//
//import java.nio.charset.StandardCharsets;
//import java.util.function.Consumer;
//
//
//@Component
//@Slf4j
//public class GateWayLoggingFilter implements GlobalFilter, Ordered {
//
//    @Override
//    public int getOrder() {
//        return Ordered.HIGHEST_PRECEDENCE;
//    }
//
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        StopWatch watch = new StopWatch();
//        watch.start();
//        long startTime = System.nanoTime();
//        ServerHttpRequest request = exchange.getRequest();
//        try {
//            //设置requestId
//            Consumer<HttpHeaders> headersConsumer = addRequestId(request, startTime);
//            //请求日志
//            LogDTO log = new LogDTO();
//            buildRequestLog(request, log);
//            //重构request
//            ServerHttpRequestDecorator requestDecorator = refactorRequest(exchange, headersConsumer, log.getRequestLog().getRequestBody());
//            //重构响应response
//            ServerHttpResponseDecorator responseDecorator = refactorResponse(exchange, log);
//            return chain.filter(exchange.mutate().request(requestDecorator).response(responseDecorator).build()).then(LogHelper.stock(log));
//        } catch (Exception e) {
//            log.error("打印日志异常", e);
//            return chain.filter(exchange);
//        }
//    }
//
//
//    /**
//     * 设置请求号
//     */
//    private Consumer<HttpHeaders> addRequestId(ServerHttpRequest request, long startTime) {
//        return httpHeaders -> {
//            final String requestId = request.getHeaders().getFirst(GateWayConstant.REQUEST_ID);
//            if (StringUtils.isBlank(requestId)) {
//                httpHeaders.set(GateWayConstant.REQUEST_ID, GenerateIdUtils.requestIdByUUID());
//            }
//            httpHeaders.set(GateWayConstant.START_TIME_KEY, String.valueOf(startTime));
//        };
//    }
//
//    /**
//     * 请求日志
//     */
//    private void buildRequestLog(ServerHttpRequest request, LogDTO logDTO) {
//        String ip = "";
//        String body = "";
//        LogDTO.RequestLog requestLog = new LogDTO.RequestLog();
//        requestLog.setRequestUrl(request.getURI().getRawPath());
//        requestLog.setRequestMethod(request.getMethod());
//        requestLog.setRequestHeaders(request.getHeaders());
//        requestLog.setRequestBody(body);
//        requestLog.setRequestIp(ip);
//        logDTO.setRequestLog(requestLog);
//    }
//
//    /**
//     * 响应日志
//     */
//    private void buildResponseLog(ServerHttpResponse response, String responseBody, LogDTO logDTO) {
//        LogDTO.ResponseLog responseLog = new LogDTO.ResponseLog();
//        responseLog.setStatus(response.getStatusCode());
//        responseLog.setResponseHeaders(response.getHeaders());
//        responseLog.setResponseBody(responseBody);
//        logDTO.setResponseLog(responseLog);
//    }
//
//    /**
//     * 重构Request
//     */
//    private ServerHttpRequestDecorator refactorRequest(ServerWebExchange exchange, Consumer<HttpHeaders> headersConsumer, String body) {
//        ServerHttpRequest witIdRequest = exchange.getRequest().mutate().headers(headersConsumer).build();
//        return new ServerHttpRequestDecorator(witIdRequest) {
//            @Override
//            public Flux<DataBuffer> getBody() {
//                NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(new UnpooledByteBufAllocator(false));
//                DataBuffer bodyDataBuffer = nettyDataBufferFactory.wrap(body.getBytes());
//                return Flux.just(bodyDataBuffer);
//            }
//        };
//    }
//
//    /**
//     * 重构Response
//     */
//    private ServerHttpResponseDecorator refactorResponse(ServerWebExchange exchange, LogDTO logDTO) {
//        ServerHttpResponse response = exchange.getResponse();
//        DataBufferFactory bufferFactory = response.bufferFactory();
//        return new ServerHttpResponseDecorator(exchange.getResponse()) {
//            @Override
//            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//                if (body instanceof Flux) {
//                    Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
//                    return super.writeWith(fluxBody.map(dataBuffer -> {
//                        byte[] content = new byte[dataBuffer.readableByteCount()];
//                        dataBuffer.read(content);
//                        String responseBody = new String(content, StandardCharsets.UTF_8);
//                        buildResponseLog(response, responseBody, logDTO);
//                        return bufferFactory.wrap(content);
//                    }));
//                }
//                return super.writeWith(body);
//            }
//        };
//    }
//}
//
